<script setup>
import { SPLITPANEL_INJECTION_KEY } from '@/components/SplitPanel/splitPanel.js'
import { useMousePressed } from '@vueuse/core'
import { provide, ref, watch } from 'vue'

const props = defineProps({
  vertical: {
    type: Boolean,
    default: false,
  },
  minSize: {
    type: Number,
    default: 50,
  },
})
// 定义常量
const LINE_WIDTH = 3

const target = ref()
const { pressed } = useMousePressed({ target })

const domEvent = ref()
const domStatus = ref(pressed)
const parentVertical = ref()

// 处理鼠标移动事件
function handleMousemove(event) {
  const { left: boxLeft, top: boxTop } = target.value.getBoundingClientRect()

  if (window.getSelection != undefined) {
    window.getSelection()?.removeAllRanges()
  }
  if (domStatus.value && domEvent.value) {
    if (!props.vertical) {
      baseSetStyleFlexBasis(
        event.clientX - boxLeft,
        domEvent.value.target.previousElementSibling.offsetLeft,
        domEvent.value.target.previousElementSibling.offsetWidth,
        domEvent.value.target.nextElementSibling.offsetWidth,
        target.value.offsetWidth,
      )
    }
    else {
      baseSetStyleFlexBasis(
        event.clientY - boxTop,
        domEvent.value.target.previousElementSibling.offsetTop,
        domEvent.value.target.previousElementSibling.offsetHeight,
        domEvent.value.target.nextElementSibling.offsetHeight,
        target.value.offsetHeight,
      )
    }
  }
}

// 更新分隔条的宽度或高度
function baseSetStyleFlexBasis(currentPoin, // 鼠标在当前splitPanel中 offsetLeft | offsetTop
  preDomOffset, // 上一个item offsetLeft | offsetTop
  preDomSize, // 上一个item offsetWidth | offsetHeight
  nextDomSize, // 下一个item offsetWidth | offsetHeight
  boxSize) {
  const prevDom = domEvent.value.target.previousElementSibling
  const nextDom = domEvent.value.target.nextElementSibling

  const otherSize = boxSize - (preDomSize + nextDomSize + LINE_WIDTH)
  const otherSizePercentage
      = ((preDomSize + nextDomSize + LINE_WIDTH) / boxSize) * 100

  if (
    currentPoin - preDomOffset < props.minSize
    || boxSize - (currentPoin - preDomOffset) - otherSize < props.minSize
  ) {
    return false
  }

  prevDom.style.flexBasis
      = `${((currentPoin - preDomOffset) / (preDomSize + nextDomSize + LINE_WIDTH))
      * otherSizePercentage
    }%`

  nextDom.style.flexBasis
      = `${((boxSize - (currentPoin - preDomOffset) - otherSize)
        / (preDomSize + nextDomSize + LINE_WIDTH))
      * otherSizePercentage
    }%`
}

// 处理鼠标移动过程中需要改变的状态
function moveChange(event, status, isVertical) {
  domEvent.value = event
  domStatus.value = status
  parentVertical.value = isVertical
  target.value.addEventListener('mousemove', handleMousemove)
}

// 处理鼠标抬起事件
function mouseup() {
  domStatus.value = false
  domEvent.value = null
  parentVertical.value = false
  target.value.removeEventListener('mousemove', handleMousemove)
}

// 定义步骤数组
const steps = ref([])

// 监听步骤数组的变化，更新每个元素的样式
watch(
  () => steps.value,
  (newVal) => {
    // 所有设置了space props的总数
    const spaces = newVal
      .filter(step => step.space)
      .map(step => step.space)

    const spaceLength = spaces.join(' - ') || '0px'
    const other = newVal.length - spaces.length

    newVal.forEach((step, index) => {
      step.setIndex(index)

      if (step.space) {
        step.itemEl.style.flexBasis = `calc(${step.space} - ${LINE_WIDTH}px)`
      }
      else {
        // 没有设置space 计算逻辑
        // ((总宽度 - 总spaces) / 没有设置space数量) = 剩下位置平分
        step.itemEl.style.flexBasis = `calc(((100% - ${spaceLength}) / ${other}) - ${LINE_WIDTH}px)`
      }
    })
  },
  { flush: 'post' },
)
// 向 lay-split-panel-item 传递参数
provide(SPLITPANEL_INJECTION_KEY, {
  props,
  steps,
  target,
  moveChange,
})
</script>

<template>
  <div
    ref="target"
    class="lay-split-panel" :class="[
      `lay-split-panel-${props.vertical ? 'vertical' : 'horizontal'}`,
    ]"
    :style="{
      cursor: domStatus ? (!props.vertical ? 'col-resize' : 'row-resize') : '',
    }"
    v-on="{ mouseup }"
  >
    <slot />
  </div>
</template>

<style lang="scss">
.lay-split-panel {
  height: 100%;
  display: flex;
  position: relative;
  .lay-split-panel-item {
    border: 1px var(--el-border-color-extra-light) solid;
    overflow: hidden;
    flex-grow: 1;
  }
  .lay-split-panel-item-move {
    user-select: none;
    pointer-events: none;
    cursor: col-resize;
  }
  .lay-split-panel-line {
    border: 1px var(--el-border-color-extra-light) solid;
    background-color: var(--global-neutral-color-1);
    border-left: none;
    border-right: none;
    display: flex;
    align-items: center;
    flex-shrink: 0;
    flex-grow: 0;
  }
}
.lay-split-panel-vertical {
  flex-direction: column;
  position: relative;
  .lay-split-panel-item-move {
    user-select: none;
    pointer-events: none;
    cursor: row-resize;
  }
  & > .lay-split-panel-line {
    display: flex;
    justify-content: center;
    width: 100%;
    height: 3px;
    cursor: row-resize;
    border: 1px var(--el-border-color-extra-light) solid;
    background-color: var(--global-neutral-color-1);
    border-top: none;
    border-bottom: none;
    &:before {
      content: "";
      height: 100%;
      width: 6px;
      border: 2px solid #dcdee2;
      border-top: none;
      border-bottom: none;
    }
  }
}
.lay-split-panel-horizontal {
  & > .lay-split-panel-line {
    height: 100%;
    width: 3px;
    cursor: col-resize;
    &:before {
      content: "";
      height: 6px;
      width: 100%;
      border: 2px solid #dcdee2;
      border-left: 0;
      border-right: 0;
    }
  }
}
</style>
